import re
import datetime

def check_id_card(id_card):

    area = {"11": "北京", "12": "天津", "13": "河北", "14": "山西", "15": "内蒙古", "21": "辽宁", "22": "吉林", "23": "黑龙江",
            "31": "上海", "32": "江苏", "33": "浙江", "34": "安徽", "35": "福建", "36": "江西", "37": "山东", "41": "河南", "42": "湖北",
            "43": "湖南", "44": "广东", "45": "广西", "46": "海南", "50": "重庆", "51": "四川", "52": "贵州", "53": "云南", "54": "西藏",
            "61": "陕西", "62": "甘肃", "63": "青海", "64": "宁夏", "65": "新疆", "71": "台湾", "81": "香港", "82": "澳门", "91": "国外"}
    id_card = str(id_card)
    id_card = id_card.strip()  # 删除前后空格

    if str(id_card[0:2]) not in area:
        print("id_card = {0}".format(id_card))
        exit('身份证地区非法!')

    # 18位身份号码检测
    if len(id_card) == 18:
        # 出生日期的合法性检查
        checkBirth(id_card)

        # 计算校验位
        M = checkCode(id_card)

        if M == id_card[17]:  # 检测ID的校验位
            exit('验证通过!')
        else:
            exit('身份证号码校验错误!')
    else:
        print("id_card = {0}".format(id_card))
        exit('身份证号码位数不对!')



    # 15位身份号码检测
    if len(id_card) == 15:
        if ((int(id_card[6:8]) + 1900) % 4 == 0 or (
                (int(id_card[6:8]) + 1900) % 100 == 0 and (int(id_card[6:8]) + 1900) % 4 == 0)):
            e_reg = re.compile(
                '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|'
                '[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$')  # //测试出生日期的合法性
        else:
            e_reg = re.compile(
                '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|'
                '[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$')  # //测试出生日期的合法性
        if re.match(e_reg, id_card):
            print('验证通过!')
        else:
            print('身份证号码出生日期超出范围或含有非法字符!')
    else:
        print("id_card = {0}".format(id_card))
        exit('身份证号码位数不对!')

def checkBirth(id_card):
    try :
        datetime.date(int(id_card[6:10]), int(id_card[10:12]), int(id_card[12:14]))
    except ValueError as ve:
        print("Datetime error: {0}".format(ve))
        exit('身份证号码出生日期超出范围或含有非法字符!')

def checkCode(id_card):
    S = (int(id_card[0]) + int(id_card[10])) * 7 + (int(id_card[1]) +
                    int(id_card[11])) * 9 + (
                    int(id_card[2]) + int(id_card[12])) * 10 + (
                    int(id_card[3]) + int(id_card[13])) * 5 + (
                    int(id_card[4]) + int(id_card[14])) * 8 + (
                    int(id_card[5]) + int(id_card[15])) * 4 + (
                    int(id_card[6]) + int(id_card[16])) * 2 + int(id_card[7]) * 1 + int(
            id_card[8]) * 6 + int(id_card[9]) * 3
    Y = S % 11
    JYM = "10X98765432"
    M = JYM[Y]  # 判断校验位

    print("17位数分别乘以不同的系数总和S={0}".format(S)+";\nS%11 ={0}".format(Y)+";\n对应校验码 ={0}".format(M)+"\nid_card={0}".format(id_card))

    return M



if __name__ == "__main__":
    while True:
        # input_card = input(u"请输入你的身份证号：")
        input_card = 412727199309288020
        if input_card == "exit":
            print(u"程序已结束！")
            break
        else:
            check_id_card(input_card)
